package mil.af.amc.adpetracker.dao.hibernate;

import mil.af.amc.adpetracker.dao.EquipmentItemDao;
import mil.af.amc.adpetracker.model.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Hibernate EquipmentItem DAO implementation
 *
 * @author TSgt Jason Ferguson
 */
 @Repository("equipmentItemDao")
public class HibernateEquipmentItemDao extends HibernateGenericDao<EquipmentItem> implements EquipmentItemDao {

    Log log = LogFactory.getLog(HibernateEquipmentItemDao.class);

    public HibernateEquipmentItemDao() {
        super(EquipmentItem.class);
    }


    public int getCountByAccount(AdpeAccount account) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        eiCriteria.add(Restrictions.eq("id", account.getId()));
        eiCriteria.setProjection(Projections.rowCount());

        return (Integer) eiCriteria.uniqueResult();
//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        crit.add(Restrictions.eq("id", account.getId()));
//        crit.setProjection(Projections.rowCount());
//        return (Integer) getHibernateTemplate().findByCriteria(crit).get(0);

    }

    public int getCountByUser(final User user) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        Criteria userCriteria = eiCriteria.createCriteria("assignedUser");
        userCriteria.add(Restrictions.eq("id", user.getId()));
        userCriteria.setProjection(Projections.rowCount());

        return (Integer) eiCriteria.uniqueResult();

//        return (Integer) getHibernateTemplate().execute(new HibernateCallback() {
//            public Object doInHibernate(Session session) throws HibernateException, SQLException {
//
//                Criteria crit = session.createCriteria(EquipmentItem.class);
//                Criteria userCrit = crit.createCriteria("assignedUser");
//                userCrit.add(Restrictions.eq("id", user.getId()));
//                userCrit.setProjection(Projections.rowCount());
//                return crit.uniqueResult();
//
//            }
//        });
    }

    @SuppressWarnings({"unchecked"})
    public EquipmentItem getBySerialNumber(String serialNumber) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        eiCriteria.add(Restrictions.eq("serial", serialNumber.toUpperCase()));

        List<EquipmentItem> results = eiCriteria.list();
//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        crit.add(Restrictions.eq("serial", serialNumber.toUpperCase()));

        return results.get(0);
//        // This is going to cause an unchecked warning, so I'll supress it for the method
//        List<EquipmentItem> results = (List<EquipmentItem>) getHibernateTemplate().findByCriteria(crit);
//
//        // Make the get() operation null-safe by checking the results and returning null if necessary... be nice if
//        // Spring's HibernateDaoSupport class had a uniqueResult() method like hibernate does
//        if (results.size() == 0) {
//            return null;
//        } else {
//            return results.get(0);
//        }

    }

    @SuppressWarnings({"unchecked"})
    public EquipmentItem getBySerialAndManufacturer(String serial, Manufacturer manu) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        eiCriteria.add(Restrictions.ilike("serial", serial));
        Criteria itemModelCriteria = eiCriteria.createCriteria("itemModel");
        Criteria manufacturerCriteria = itemModelCriteria.createCriteria("manufacurer");
        manufacturerCriteria.add(Restrictions.eq("id", manu.getId()));

        List<EquipmentItem> results = eiCriteria.list();

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        crit.add(Restrictions.ilike("serial", serial));
//        DetachedCriteria itemModelCrit = crit.createCriteria("itemModel");
//        DetachedCriteria manufacturerCrit = itemModelCrit.createCriteria("manufacturer");
//        manufacturerCrit.add(Restrictions.eq("id", manu.getId()));
//
//        List<EquipmentItem> results = (List<EquipmentItem>) getHibernateTemplate().findByCriteria(crit);

        if (results.size() == 0) {
            return null;
        } else {
            return results.get(0);
        }
    }

    @SuppressWarnings("unchecked")
    public List<EquipmentItem> getAllByAccount(final AdpeAccount account) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        Criteria aaCriteria = eiCriteria.createCriteria("account");
        aaCriteria.add(Restrictions.eq("id", account.getId()));

        List<EquipmentItem> results = eiCriteria.list();

        return results;

//        return (List<EquipmentItem>) getHibernateTemplate().execute(new HibernateCallback() {
//            public Object doInHibernate(Session session) throws HibernateException, SQLException {
//                Criteria crit = session.createCriteria(EquipmentItem.class);
//                Criteria subCrit = crit.createCriteria("account");
//                subCrit.add(Restrictions.eq("id", account.getId()));
//
//                return crit.list();
//            }
//        });

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        crit.add(Restrictions.eq("Account", account));
//        return (List<EquipmentItem>) getHibernateTemplate().findByCriteria(crit);

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getAllActiveByAccount(final AdpeAccount account) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        eiCriteria.add(Restrictions.eq("AdpeAccount", account));


        //DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
        //crit.add(Restrictions.eq("AdpeAccount", account));
        //crit.add(Restrictions.isNull("drmoDate"));
        //crit.add(Restrictions.isNull("rosDate"));

        List<EquipmentItem> resultList = null;
        try {
            resultList = (List<EquipmentItem>) eiCriteria.list();
        } catch (DataAccessException e) {
            log.debug(e);
        }

        return resultList;

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getAllCurrentByAccount(AdpeAccount account) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        Criteria aaCritieria = eiCriteria.createCriteria("account");
        aaCritieria.add(Restrictions.eq("id", account.getId()));
        eiCriteria.add(Restrictions.isNull("drmoPackage"));
        eiCriteria.add(Restrictions.isNull("rosPackage"));

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        DetachedCriteria acctCrit = crit.createCriteria("account");
//        acctCrit.add(Restrictions.eq("id", account.getId()));
//        crit.add(Restrictions.isNull("drmoPackage"));
//        crit.add(Restrictions.isNull("rosPackage"));

        List<EquipmentItem> resultList = null;
        try {
            resultList = (List<EquipmentItem>) eiCriteria.list();
        } catch (DataAccessException e) {
            e.printStackTrace();
            log.debug(e);
        }
        return resultList;

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getAllByModel(ItemModel model) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        eiCriteria.add(Restrictions.eq("itemModel", model));

        //DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
        //crit.add(Restrictions.eq("itemModel", model));
        //crit.add(Restrictions.isNull("drmoDate"));
        //crit.add(Restrictions.isNull("rosDate"));
        List<EquipmentItem> resultList = (List<EquipmentItem>) eiCriteria.list();

        return resultList;

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getByItemType(EquipmentType itemType) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        Criteria typeCritieria = eiCriteria.createCriteria("equipmentType");
        typeCritieria.add(Restrictions.eq("id", itemType.getId()));

        List<EquipmentItem> results = eiCriteria.list();

        return results;

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        DetachedCriteria typeCrit = crit.createCriteria("equipmentType");
//        typeCrit.add(Restrictions.eq("id", itemType.getId()));
//
//        return getHibernateTemplate().findByCriteria(crit);

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getAllByUserAndAdpeAccount(User user, AdpeAccount acct) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);

        Criteria userCriteria = eiCriteria.createCriteria("assignedUser");
        userCriteria.add(Restrictions.eq("id", user.getId()));

        Criteria aaCriteria = eiCriteria.createCriteria("account");
        aaCriteria.add(Restrictions.eq("id", acct.getId()));

        List<EquipmentItem> results = eiCriteria.list();

        return results;
//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//
//        DetachedCriteria userCrit = crit.createCriteria("assignedUser");
//        userCrit.add(Restrictions.eq("id", user.getId()));
//
//        DetachedCriteria acctCrit = crit.createCriteria("account");
//        acctCrit.add(Restrictions.eq("id", acct.getId()));
//
//        return getHibernateTemplate().findByCriteria(crit);

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getByAdpeAccountAndEquipmentTypeAndManufacturer(AdpeAccount acct,
                                                                               EquipmentType type,
                                                                               Manufacturer manu) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);

        //DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);

        // Exclude anything that has been DRMO'd or ROS'd
        eiCriteria.add(Restrictions.or(
                Restrictions.not(Restrictions.eq("status", Status.Drmo)),
                Restrictions.not(Restrictions.eq("status", Status.Ros))));
        // if all three are null, then the user wants all results
        if (acct == null && type == null & manu == null) {

            List<EquipmentItem> results = eiCriteria.list();

            return results;
        }


        if (acct != null) {
            Criteria aaCriteria = eiCriteria.createCriteria("account");
            aaCriteria.add(Restrictions.eq("id", acct.getId()));
        }

        if (type != null) {

            Criteria typeCriteria = eiCriteria.createCriteria("equipmentType");
            typeCriteria.add(Restrictions.eq("id", type.getId()));
        }

        Criteria itemModelCriteria = eiCriteria.createCriteria("itemModel");
        if (manu != null) {
            Criteria manufacturerCriteria = itemModelCriteria.createCriteria("manufacturer");
            manufacturerCriteria.add(Restrictions.eq("id", manu.getId()));
        }
        List<EquipmentItem> results = eiCriteria.list();

        return results;

    }

    @SuppressWarnings({"unchecked"})
    public List<EquipmentItem> getItemsByQbe(EquipmentItem item) {

        Criteria eiCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);

        if (item.getAccount() != null) {
            Criteria aaCriteria = eiCriteria.createCriteria("account");
            Example e = Example.create(item.getAccount());
            aaCriteria.add(e);
        }

        if (item.getItemModel()!= null) {
            Criteria itemModelCriteria = eiCriteria.createCriteria("itemModel");
            Example e = Example.create(item.getItemModel());
            itemModelCriteria.add(e);
        }

        return eiCriteria.list();
        //return (List<EquipmentItem>) getHibernateTemplate().findByCriteria(crit);
    }

}
